#ifndef RLSPACKET_H
#define RLSVPACKET_H

#include <iostream>
#include "ns3/header.h"
#include "ns3/ipv4-address.h"
#include "ns3/vector.h"
#include "ns3/timer.h"

namespace ns3 {
namespace sls {

enum MessageType{
	SLS_LOCATION_QUERY = 1,
	SLS_LOCATION_REPLY = 2,
};

class TypeHeader : public Header
{
public:
  /// c-tor
  TypeHeader (MessageType t);

  ///\name Header serialization/deserialization
  //\{
  static TypeId GetTypeId ();
  TypeId GetInstanceTypeId () const;
  uint32_t GetSerializedSize () const;
  void Serialize (Buffer::Iterator start) const;
  uint32_t Deserialize (Buffer::Iterator start);
  void Print (std::ostream &os) const;
  //\}

  MessageType Get () const { return m_type; }
  bool IsValid () const { return m_valid; }
  bool operator== (TypeHeader const & o) const;
private:
  MessageType m_type;
  bool m_valid;
};

class LocQueryHeader : public Header
{
public:
	//Constructor
	LocQueryHeader(Ipv4Address nodeIdDst = Ipv4Address::GetZero (), Vector nodePosSrc = Vector (-1, -1, 0), Ipv4Address nodeIdSrc = Ipv4Address::GetZero (), uint32_t seqNumber = 0,  uint8_t ttl = 1);
	
	///\name Header serialization/deserialization
    //\{
	static TypeId GetTypeId ();
	TypeId GetInstanceTypeId () const;
	uint32_t GetSerializedSize () const;
	void Serialize (Buffer::Iterator start) const;
	uint32_t Deserialize (Buffer::Iterator start);
	void Print (std::ostream &os) const;
	//\}

	void SetSrcId (Ipv4Address id) { m_nodeIdSrc = id; }
	Ipv4Address GetSrcId () const { return m_nodeIdSrc; }
	void SetDstId (Ipv4Address id) { m_nodeIdDst = id; }
	Ipv4Address GetDstId () const { return m_nodeIdDst; }
	void SetSrcPos (Vector pos) { m_nodePosSrc.x = pos.x; m_nodePosSrc.y = pos.y; }
	Vector GetSrcPos () const { return m_nodePosSrc; }
	void SetMessageSeqNum (uint32_t s) { m_seqNumber = s; }
	uint32_t GetMessageSeqNum () const { return m_seqNumber; }
	void SetTTL (uint8_t count) { m_ttl = count; }
	uint8_t GetTTL () const { return m_ttl; }

	bool operator== (LocQueryHeader const & o) const;

private:
	Ipv4Address m_nodeIdDst;
	Vector m_nodePosSrc;
	Ipv4Address m_nodeIdSrc;
	uint32_t m_seqNumber;
	uint8_t m_ttl; //time-to-live (number of hops)
};

class LocReplyHeader : public Header
{
public:
	//Constructor
	LocReplyHeader(Ipv4Address nodeIdDst = Ipv4Address::GetZero (), Vector nodePosSrc = Vector (-1, -1, 0), Vector nodePosDst = Vector (-1, -1, 0),
				   Ipv4Address nodeIdSrc = Ipv4Address::GetZero (), uint32_t seqNumber = 0, uint8_t ttl = 1);

	///\name Header serialization/deserialization
    //\{
	static TypeId GetTypeId ();
	TypeId GetInstanceTypeId () const;
	uint32_t GetSerializedSize () const;
	void Serialize (Buffer::Iterator start) const;
	uint32_t Deserialize (Buffer::Iterator start);
	void Print (std::ostream &os) const;
	//\}

	void SetSrcId (Ipv4Address id) { m_nodeIdSrc = id; }
	Ipv4Address GetSrcId () const { return m_nodeIdSrc; }
	void SetDstId (Ipv4Address id) { m_nodeIdDst = id; }
	Ipv4Address GetDstId () const { return m_nodeIdDst; }
	void SetSrcPos (Vector pos) { m_nodePosSrc.x = pos.x; m_nodePosSrc.y = pos.y; }
	Vector GetSrcPos () const { return m_nodePosSrc; }
	void SetDstPos (Vector pos) { m_nodePosDst.x = pos.x; m_nodePosDst.y = pos.y; }
	Vector GetDstPos () const { return m_nodePosDst; }
	void SetMessageSeqNum (uint32_t s) { m_seqNumber = s; }
	uint32_t GetMessageSeqNum () const { return m_seqNumber; }
	void SetTTL (uint8_t count) { m_ttl = count; }
	uint8_t GetTTL () const { return m_ttl; }

	bool operator== (LocReplyHeader const & o) const;

private:
	Ipv4Address m_nodeIdDst;
	Vector m_nodePosSrc;
	Vector m_nodePosDst;
	Ipv4Address m_nodeIdSrc;
	uint32_t m_seqNumber;
	uint8_t m_ttl; //time-to-live (number of hops)
};

std::ostream & operator<< (std::ostream & os, TypeHeader const & h);
std::ostream & operator<< (std::ostream & os, LocQueryHeader const & h);
std::ostream & operator<< (std::ostream &os, LocQueryHeader const &h);

}
}
#endif
